﻿
namespace n_MyFileObject
{
using System;
using n_GUIcoder;
using n_MyObject;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Collections.Generic;
using n_OS;

//*****************************************************
//组件类
public abstract class MyFileObject: MyObject
{
	//public string Name;
	//public int X, Y;
	//public int Angle;  // 0, 90, 180, 240
	//public int Width, Height;
	//public bool isMousePress;
	//int Last_mX, Last_mY;
	
	public string Version;
	
	public string ImageName;
	public string[] NameList;
	
	public bool isClientChannel;
	public bool isControlModule;
	public bool isUserPathMod;
	
	public bool CanSwap;
	
	//组件占用的资源列表
	public string[] ResourceList;
	
	//图形控件属性列表
	public string[] UIModuleEXList;
	
	//和此组件相关联的程序包文件路径 带有inc和空格前缀的路径, 仅用于include指令
	public string IncPackFilePath;
	
	//py文件完整路径 (如果有的话)
	public string PyFilePath;
	public string PyFile;
	
	//生成本模块的宏配置文件 完整路径
	public string MacroFilePath;
	
	//生成本模块的宏配置文件 相对路径, 带有前缀 ModuleLib, 根据类型可能为.M扩展名或者.B扩展名
	public string MacroFilePathPart;
	
	//此组件所在的路径 带有inc和空格前缀的路径, 仅用于include指令
	public string IncBasePath;
	
	//本模块所在的根目录 完整路径
	public string BasePath;
	
	//仿真类型
	public int SimulateType;
	
	//py参数
	public string PyValue;
	
	//公共引用路径
	public string CommonRefFile;
	
	//实物图片列表，以逗号分隔，没有图片的话为empty
	public string ModuleImageList;
	
	//模块型号
	public string ChipType;
	
	//说明文档路径
	public string MesFilePath;
	
	//扩展参数
	public string EXMes;
	
	//组件支持的语言列表
	public string[] LanguageList;
	public string Language;
	
	//组件的接口列表
	//每个项的第0个元素(0)存放用户的名称,第1个为interface_Func,第2个为innerName,以下依次为其他语言
	public string[][] InterfaceList;
	
	//组件的需求接口列表
	//每个项的第0个元素(0)存放用户的名称,第1个为linkinterface_Func,第2个为innerName,以下依次为其他语言
	public string[][] LinkInterfaceList;
	
	//组件的事件处理列表
	//每个项的第0个元素(0)存放用户的名称,第1个为innerName,以下依次为其他语言
	public string[][] EventList;
	
	//组件的参数列表
	//每个项的第0个元素(0)存放用户的名称,第1个为innerName,以下依次为其他语言
	public string[][] VarList;
	
	//组件元素列表
	public string[][] ElementList;
	
	//组件扩展信息列表
	public ModuleMessage[] mm;
	
	//背景颜色
	protected Brush BackBrush;
	Color vvBackColor;
	public Color BackColor {
		get { return vvBackColor; }
		set {
			vvBackColor = value;
			BackBrush = new SolidBrush( vvBackColor );
		}
	}
	
	//边框颜色
	protected Pen FramePen;
	Color vvFrameColor;
	public Color FrameColor {
		get { return vvFrameColor; }
		set {
			vvFrameColor = value;
			FramePen = new Pen( vvFrameColor );
		}
	}
	
	//文字颜色
	protected Brush ForeBrush;
	Color vvForeColor;
	public Color ForeColor {
		get { return vvForeColor; }
		set {
			vvForeColor = value;
			ForeBrush = new SolidBrush( vvForeColor );
		}
	}
	
	//文字信息
	public string Text;
	
	//扩展信息
	public string v_ExtendValue;
	protected string KeyMes;
	protected int TickMesN;
	public string ExtendValue {
		set {
			v_ExtendValue = value;
			if( ImageName == SPMoudleName.SYS_Keyboard ) {
				if( myKeyNote != null ) {
					myKeyNote.ResetKey();
				}
				string[] s = v_ExtendValue.Split( ' ' );
				KeyMes = s[0];
				string TickMes = s[1];
				TickMesN = int.Parse( TickMes );
			}
		}
		get {
			return v_ExtendValue;
		}
	}
	public n_Keyboard.KeyNote myKeyNote;
	
	//扩展信息1
	public string ExtendValue1;
	
	//扩展信息1
	//public string[] ExtendValueList;
	//public const int 
	
	//字体
	public Font TextFont;
	
	public const int IPort2R = 20;
	
	public IPort[] IPortList;
	public void SetIPortListOwner( MyFileObject m )
	{
		for( int i = 0; i < IPortList.Length; ++i ) {
			IPortList[i].Owner = m;
		}
	}
	
	//构造函数,根据文件名加载组件,文件名为全路径
	public MyFileObject(): base()
	{
		ignoreHit = false;
		isUserPathMod = false;
		
		ExYLPadding = 0;
		ExYHPadding = 0;
		
		CommonRefFile = null;
		ResourceList = null;
		LanguageList = null;
		Language = null;
		SimulateType = 0;
		
		IPortList = null;
		
		BackColor = Color.White;
		FrameColor = Color.Black;
		ForeColor = Color.Black;
		TextFont = new Font( "宋体", 12 );
		Text = "";
		ExtendValue = "";
		ExtendValue1 = "";
		
		ModuleImageList = "";
		ChipType = "";
	}
	
	//创建接口端点列表
	public void CreateIPortList()
	{
		//注意: 添加顺序不能交换, InterfaceList在前, LinkInterfaceList在后. 因为需要根据索引查找对应的interface
		IPortList = new IPort[ this.InterfaceList.Length + this.LinkInterfaceList.Length ];
		int index = 0;
		if( this.InterfaceList.Length != 0 ) {
			
			//2020.3.14 更新: 不再支持从硬件到引擎的连接, 而是点击引擎的菜单按钮直接连接到目标硬件
			//ExYHPadding = IPort2R;
			
			int StepStart = this.Width / this.InterfaceList.Length / 2 - this.Width / 2;
			int StepLength = this.Width / this.InterfaceList.Length;
			for( int i = 0; i < this.InterfaceList.Length; ++i ) {
				IPortList[index] = new IPort( this, false, i, StepStart, - this.Height / 2 + 10 ); //- ExYHPadding / 2 );
				index++;
				StepStart += StepLength;
			}
		}
		if( this.LinkInterfaceList.Length != 0 ) {
			ExYLPadding = IPort2R;
			int StepStart = this.Width / this.LinkInterfaceList.Length / 2 - this.Width / 2;
			int StepLength = this.Width / this.LinkInterfaceList.Length;
			for( int i = 0; i < this.LinkInterfaceList.Length; ++i ) {
				IPortList[index] = new IPort( this, true, i, StepStart, this.Height / 2 + ExYLPadding / 2 );
				index++;
				StepStart += StepLength;
			}
		}
	}
	
	//刷新接口端点列表, 当控件尺寸改变时需要调用
	public void RefreshIPortList()
	{
		//注意: 添加顺序不能交换, InterfaceList在前, LinkInterfaceList在后. 因为需要根据索引查找对应的interface
		if( this.InterfaceList.Length + this.LinkInterfaceList.Length == 0 ) {
			return;
		}
		
		int index = 0;
		if( this.InterfaceList.Length != 0 ) {
			int StepStart = this.Width / this.InterfaceList.Length / 2 - this.Width / 2;
			int StepLength = this.Width / this.InterfaceList.Length;
			for( int i = 0; i < this.InterfaceList.Length; ++i ) {
				IPortList[index].MidX = StepStart;
				IPortList[index].MidY = - this.Height / 2 - ExYHPadding / 2;
				index++;
				StepStart += StepLength;
			}
		}
		if( this.LinkInterfaceList.Length != 0 ) {
			int StepStart = this.Width / this.LinkInterfaceList.Length / 2 - this.Width / 2;
			int StepLength = this.Width / this.LinkInterfaceList.Length;
			for( int i = 0; i < this.LinkInterfaceList.Length; ++i ) {
				IPortList[index].MidX = StepStart;
				IPortList[index].MidY = - this.Height / 2 + 10; //- ExYHPadding / 2;
				index++;
				StepStart += StepLength;
			}
		}
	}
	
	//删除
	protected void CommonRemove()
	{
		//遍历组件列表,查找所有指向目标组件的链接,如果存在则提示是否删除
		foreach( MyObject mo in myObjectList ) {
		
			if( !(mo is MyFileObject) ) {
				continue;
			}
			MyFileObject cM = (MyFileObject)mo;
			
			//查找所有相关链接
			for( int n = 0; n < cM.LinkInterfaceList.Length; ++n ) {
				if( cM.LinkInterfaceList[ n ][ 0 ] != "" ) {
					string[] cut = cM.LinkInterfaceList[ n ][ 0 ].Split( ' ' );
					string LinkTargetModuleName = cut[0].Split( '.' )[0];
					if( LinkTargetModuleName == this.Name ) {
						cM.LinkInterfaceList[ n ][ 0 ] = "";
						cM.IPortList[cM.InterfaceList.Length + n].TargetIPort = null;
					}
				}
			}
		}
		
		//删除事件列表
		for( int ei = 0; ei < this.EventList.Length; ++ei ) {
			string EventEntry = this.EventList[ ei ][ 0 ];
			if( EventEntry == "" ) {
				continue;
			}
			myObjectList.GPanel.EL.Delete( this, this.EventList[ ei ][ 2 ] );
		}
		//遍历组件列表,查找当前组件
		for( int i = 0; i < myObjectList.MLength; ++i ) {
			if( myObjectList.ModuleList[ i ] == this ) {
				myObjectList.ModuleList[ i ] = null;
				return;
			}
		}
	}
	
	//获取语言序号列
	public int GetLC()
	{
		return GetLIndex() + 3;
	}
	
	//获取语言序号
	public int GetLIndex()
	{
		for( int i = 0; i < LanguageList.Length; ++i ) {
			if( LanguageList[ i ] == Language ) {
				return i;
			}
		}
		return 0;
	}
	
	//获取某个中文成员的内部名称
	public string GetInnerName( string Name )
	{
		int LIndex = GetLC();
		
		
		//因为语言已改为c, 所以需要加上1
		LIndex += 1;
		
		
		
		for( int i = 0; i < ElementList.Length; ++i ) {
			string[] cut = ElementList[ i ][ LIndex ].Split( '+' );
			
			string s = "";
			for( int n = 0; n < cut.Length; ++n ) {
				if( cut[n] == "#" ) {
					s += "_";
				}
				else {
					s += cut[n];
				}
			}
			if( s == Name ) {
				return ElementList[ i ][ 2 ];
			}
		}
		return null;
	}
	
	//绘制接口
	protected void DrawInterface( Graphics g )
	{
		for( int i = 0; i < IPortList.Length; ++i ) {
			IPortList[i].Draw( g );
		}
	}
	
	//复位接口位置
	protected void ResetInterfaceLocation()
	{
		for( int i = 0; i < IPortList.Length; ++i ) {
			IPortList[i].ResetLocation();
		}
	}
	
	//接口鼠标按下事件
	protected bool IPortListMouseDown( int mX, int mY )
	{
		for( int i = 0; i < IPortList.Length; ++i ) {
			if( !IPortList[i].isLink && myObjectList.SelectIPort == null ) {
				continue;
			}
			if( IPortList[ i ].isMouseInPort( mX, mY  ) ) {
				if( this.myObjectList.SelectIPort != null ) {
					
					//排列主从连接关系
					IPort LinkInterfaceIPort = null;
					IPort InterfaceIPort = null;
					if( this.myObjectList.SelectIPort.isLink ) {
						LinkInterfaceIPort = this.myObjectList.SelectIPort;
					} else {
						InterfaceIPort = this.myObjectList.SelectIPort;
					}
					if( IPortList[ i ].isLink ) {
						LinkInterfaceIPort = IPortList[ i ];
					} else {
						InterfaceIPort = IPortList[ i ];
					}
					if( LinkInterfaceIPort == null || InterfaceIPort == null ) {
						n_Debug.Warning.WarningMessage = ( "只能把需求端口和提供端口连接起来, 而不能连接同类端口" );
						break;
					}
					if( LinkInterfaceIPort.Owner == InterfaceIPort.Owner ) {
						n_Debug.Warning.WarningMessage = ( "接口不能连接到自身上" );
						break;
					}
					//判断连接类型是否匹配
					string LinkType = LinkInterfaceIPort.Owner.LinkInterfaceList[ LinkInterfaceIPort.Index ][ 1 ].Split( '_' )[ 1 ];
					string TargetType = InterfaceIPort.Owner.InterfaceList[ InterfaceIPort.Index ][ 1 ].Split( '_' )[ 1 ];
					if( LinkType != TargetType ) {
						n_Debug.Warning.WarningMessage = ( "接口类型不相同, 无法连接: " + LinkType + " - " + TargetType );
						break;
					}
					string Target =	InterfaceIPort.Owner.Name + "." + InterfaceIPort.Owner.InterfaceList[ InterfaceIPort.Index ][ 2 ];
					LinkInterfaceIPort.Owner.LinkInterfaceList[ LinkInterfaceIPort.Index ][ 0 ] = Target;
					LinkInterfaceIPort.TargetIPort = InterfaceIPort;
					this.myObjectList.SelectIPort = null;
				}
				else {
					if( IPortList[ i ].isLink ) {
						IPortList[ i ].TargetIPort = null;
						this.LinkInterfaceList[ IPortList[ i ].Index ][ 0 ] = "";
					}
					this.myObjectList.SelectIPort = IPortList[ i ];
				}
				return true;
			}
		}
		return false;
	}
}
//接口端点类
public class IPort
{
	public MyFileObject Owner;
	public bool isLink;
	public int Index;
	
	public int SourceX;
	public int SourceY;
	public int MidX;
	public int MidY;
	public int Width;
	public int Height;
	
	public IPort TargetIPort;
	Font f;
	
	const int PortR = 9;
	
	//构造函数
	public IPort( MyFileObject v_owner, bool v_isLink, int v_index, int x, int y )
	{
		Owner = v_owner;
		isLink = v_isLink;
		Index = v_index;
		
		TargetIPort = null;
		
		Width = MyFileObject.IPort2R;
		Height = MyFileObject.IPort2R;
		
		SourceX = x;
		SourceY = y;
		
		MidX = x;
		MidY = y;
		
		f = new Font( "微软雅黑", 12 );
	}
	
	//复位位置
	public void ResetLocation()
	{
		MidX = (int)(SourceX * ((n_HardModule.HardModule)this.Owner).CScale);
		MidY = (int)(SourceY * ((n_HardModule.HardModule)this.Owner).CScale);
	}
	
	//获取对应的接口字符串数组信息
	public string[] GetMessage()
	{
		if( isLink ) {
			return Owner.LinkInterfaceList[ Index ];
		}
		else {
			return Owner.InterfaceList[ Index ];
		}
	}
	
	//更新接口目标(防止目标改名后编译出错)
	public void Refresh()
	{
		if( TargetIPort != null ) {
			string cn = Owner.LinkInterfaceList[Index][0];
			string tn = TargetIPort.Owner.Name + "." + TargetIPort.Owner.InterfaceList[TargetIPort.Index][2];
			if( cn != tn ) {
				//n_Debug.Debug.Message += "ERROR:" + cn + "-" + tn + " ";
				Owner.LinkInterfaceList[Index][0] = tn;
			}
		}
	}
	
	//绘制端口
	public void Draw( Graphics g )
	{
		if( !isLink && Owner.myObjectList.SelectIPort == null ) {
			return;
		}
		Point[] pt = new Point[ 5 ];
		pt[ 0 ] = new Point( Owner.MidX + MidX - PortR, Owner.MidY + MidY - PortR );
		pt[ 1 ] = new Point( Owner.MidX + MidX + PortR, Owner.MidY + MidY - PortR );
		pt[ 2 ] = new Point( Owner.MidX + MidX + PortR, Owner.MidY + MidY );
		pt[ 3 ] = new Point( Owner.MidX + MidX, Owner.MidY + MidY + PortR );
		pt[ 4 ] = new Point( Owner.MidX + MidX - PortR, Owner.MidY + MidY );
		
		g.FillClosedCurve( Brushes.ForestGreen, pt, FillMode.Winding, 0.0F );
	}
	
	//绘制鼠标悬停端口
	public void DrawHighLight( Graphics g )
	{
		if( !isLink && Owner.myObjectList.SelectIPort == null ) {
			return;
		}
		Point[] pt = new Point[ 5 ];
		pt[ 0 ] = new Point( Owner.MidX + MidX - PortR, Owner.MidY + MidY - PortR );
		pt[ 1 ] = new Point( Owner.MidX + MidX + PortR, Owner.MidY + MidY - PortR );
		pt[ 2 ] = new Point( Owner.MidX + MidX + PortR, Owner.MidY + MidY );
		pt[ 3 ] = new Point( Owner.MidX + MidX, Owner.MidY + MidY + PortR );
		pt[ 4 ] = new Point( Owner.MidX + MidX - PortR, Owner.MidY + MidY );
		
		g.FillClosedCurve( Brushes.OrangeRed, pt, FillMode.Winding, 0.0F );
		//g.DrawClosedCurve( Pens.DarkRed, pt );
		
		string[] IList = GetMessage();
		int YOffset = -20;
		if( isLink ) {
			YOffset = 20;
		}
		if( n_MainSystemData.SystemData.isBlack ) {
			g.DrawString( IList[2] + "(" + IList[1] + ")", f, Brushes.WhiteSmoke, Owner.MidX + MidX, Owner.MidY + MidY - 10 + YOffset );
		}
		else {
			g.DrawString( IList[2] + "(" + IList[1] + ")", f, Brushes.DarkSlateGray, Owner.MidX + MidX, Owner.MidY + MidY - 10 + YOffset );
		}
	}
	
	//判断鼠标是否在端口上
	public bool isMouseInPort( int mX, int mY )
	{
		int offX = mX - Owner.MidX;
		int offY = mY - Owner.MidY;
		
		int PortR = MyFileObject.IPort2R / 2;
		
		if( offX >= MidX - PortR && offX <= MidX + PortR &&
			offY >= MidY - PortR && offY <= MidY + PortR ) {
			return true;
		}
		else {
			return false;
		}
	}
}
}

